package snu.bi.MSAgent.Estimator;

import java.util.Calendar;
import java.util.TimeZone;

import snu.bi.MSAgent.ActRecog.ActionService;
import snu.bi.MSAgent.DB.MSADBHandler;
import android.database.Cursor;

public class WeightEstimator {
        
        public static final int BASAL_METABOLISM = 0;
        public static final int BMI = 1;
                
        private double [] coefficientMan = {66.47, 13.75, 5, 6.67};
        private double [] coefficientWoman = {66.47, 13.75, 5, 6.67};
        
        public static final double caloriesForLose1Kg = 7700; /* kcal */ 
        
        private MSADBHandler hDB;
        
        private double weight;
        private double height;
        private int age;
        private int gender;
        private double 일일신진대사량;
                
        public WeightEstimator(MSADBHandler hDB){
//			this.statusHandler = MSAUserStatHandler.open(c);
//			this.menuLogHandler = MSAMenuLogHandler.open(c);
//			
//			this.currentStatus = this.statusHandler.readMostRecentUserStat();
//			this.gender = MSAUserInfoHandler.getUserInfo(c).gender;
        	TimeZone timezone = TimeZone.getTimeZone("Etc/GMT-9");
            TimeZone.setDefault(timezone);
        	
        	this.hDB = hDB;
        	double [] factor = this.calcFactor();
        	double basal = factor[WeightEstimator.BASAL_METABOLISM];
        	double bmi = factor[WeightEstimator.BMI];

        	//this.일일신진대사량 = basal + basal*1/2 +  basal*1/6; /* 기초대사량, 활동대사량, DIT. 한 방에 구할 수 있으나, 가독성을 위해...*/
        	this.일일신진대사량 = basal;
        	
        	
        	// TEST
        	
        }
        public double cals_per_min(double MET) {
        	return get_a_min_dayday()+0.0175*MET*weight;
        }
        public double cal_to_fitness() {
        	double bmi = get_bmi();
        	if(bmi <= 18) {
    			return 256.66;
    		}
    		else if(bmi >= 28) {
    			return -770.0;
    		}
    		else if(bmi >= 23) {
    			return -256.66;
    		}
    		else {
    			return 0.0;
    		}
        }
        public double get_bmi() {
        	double bmi=20;
        	String query;
        	
        	query = "select value from bmi_table order by time desc limit 1;";        	
        	Cursor result = this.hDB.rawQuery(query);
        	result.moveToFirst();
        	if(result.getCount()>0) bmi = result.getDouble(0);
        	result.close();
        	
        	return bmi;
        }
        public double get_a_min_dayday() {
        	return 일일신진대사량/1440;
        }
        private double [] calcFactor(){
			weight = 0; height = 0; age = 0; gender = 0;
        	String query;
        	
        	query = "select value from weight_table order by time desc limit 1;";        	
        	Cursor result = this.hDB.rawQuery(query);
        	result.moveToFirst();
        	if(result.getCount()>0) this.weight = result.getDouble(0);
        	result.close();
        	
        	query = "select value from height_table order by time desc limit 1;";
        	result = this.hDB.rawQuery(query);
        	result.moveToFirst();
        	if(result.getCount()>0) this.height = result.getDouble(0);
        	result.close();
        	
        	query = "select value from age_table order by time desc limit 1;";
        	result = this.hDB.rawQuery(query);
        	result.moveToFirst();
        	if(result.getCount()>0) this.age = result.getInt(0);
        	result.close();
        	
        	query = "select value from sex_table order by time desc limit 1;";
        	result = this.hDB.rawQuery(query);
        	result.moveToFirst();
        	if(result.getCount()>0) this.gender = result.getInt(0);
        	result.close();
        	
			
			double [] retVal = new double[2];
			
			if( gender == 0 ){				
			        retVal[0] = this.coefficientMan[0] + (this.coefficientMan[1]*weight) + (this.coefficientMan[2]*height) - (this.coefficientMan[3]*age);
			}else{
			        retVal[0] = this.coefficientWoman[0] + (this.coefficientWoman[1]*weight) + (this.coefficientWoman[2]*height) - (this.coefficientWoman[3]*age);
			}
			
			retVal[1] = (this.weight/Math.pow(height/100, 2));
			
			return retVal;
                
        }
        
        public double calculateIntakeCalories(int days){
//			double [] abracadabra = this.calcFactor();
//			double basal = abracadabra[0];
//			double bmi = abracadabra[1];
//			
//			double [] factor = {basal, basal*1/2, basal*1/6}; /* 기초대사량, 활동대사량, DIT */
//			double 일일신진대사량 = factor[0] + factor[1] + factor[2];
			
			/* 지난 24시간 동안 먹은 칼로리 가져오기 */
			//long currentTime = Long.parseLong(this.currentStatus.time);
			long now = new java.util.Date().getTime();
			long before = now;
			for(int i=0; i<days; i++) before = before - 86400000;
			//this.menuList = this.menuLogHandler.readMenuLog(currentTime - 24*60*60*1000, currentTime);
			String query;
			query = "select menu from menu_log where time <= " + now + " and time >= " + before + ";";
			Cursor result = this.hDB.rawQuery(query);
			
			double calorySum = 0;
			result.moveToFirst();
			
			int count = 0;
			if ( (count = result.getCount()) > 0){
				
				/* 분기문 하나에 처리하는게 나은 것 같아서 하나로 처리함 */
				Cursor menuCalories;
				for(int i = 0; i < count; i++){
					query = "select calories from menu where _id = " + result.getInt(0) + ";";
					menuCalories = this.hDB.rawQuery(query);
					menuCalories.moveToFirst();
					calorySum += menuCalories.getDouble(0);
					menuCalories.close();
					result.moveToNext();
				}
			}else{
				// error
			}
			
			result.close();
			
			return calorySum;
			
			//double changedWeight = rest / WeightEstimator.caloriesForLose1Kg;
			
			//return this.weight + changedWeight;
        }
        
//        public double calculateRestCaloriesForMonth(){
////			double [] abracadabra = this.calcFactor();
////			double basal = abracadabra[0];
////			double bmi = abracadabra[1];
////			
////			double [] factor = {basal, basal*1/2, basal*1/6}; /* 기초대사량, 활동대사량, DIT */
////			double 일일신진대사량 = 30 * (factor[0] + factor[1] + factor[2]);
//			
//			/* 지난 24시간 동안 먹은 칼로리 가져오기 */
//			//long currentTime = Long.parseLong(this.currentStatus.time);
//			long now = new java.util.Date().getTime();
//			
//			//this.menuList = this.menuLogHandler.readMenuLog(currentTime - 24*60*60*1000, currentTime);
//			String query;
//			query = "select menu from menu_log where time <= " + now + " and time >= " + (now - (30*24*3600*1000)) + ";";
//			Cursor result = this.hDB.rawQuery(query);
//			
//			double calorySum = 0;
//			result.moveToFirst();
//			
//			int count = 0;
//			if ( (count = result.getCount()) > 0){
//				
//				/* 분기문 하나에 처리하는게 나은 것 같아서 하나로 처리함 */
//				Cursor menuCalories;
//				for(int i = 0; i < count; i++){
//					query = "select calories from menu where _id = " + result.getInt(0) + ";";
//					menuCalories = this.hDB.rawQuery(query);
//					menuCalories.moveToFirst();
//					calorySum += menuCalories.getDouble(0);
//					menuCalories.close();
//				}
//			}else{
//				// error
//			}
//			
//			double rest = calorySum - 일일신진대사량;
//			
//			return rest;
//			
//			//double changedWeight = rest / WeightEstimator.caloriesForLose1Kg;
//			
//			//return this.weight + changedWeight;
//        }
        
        /* 24시간 동안 소모한 칼로리 계산 */
        public double burnedUpCalories(int days){
        	
        	// 운동로그 테이블을 참조하여 운도으로 소모된 칼로리 계산
        	// 일일신진대사량 * days 한 만큼을 감산
        	// 그 값을 리턴
        	
        	/* 데이터 베이스에서 현재 시각 기준 24시간 이전의 데이터들을 소거 */
        	//String query = "SELECT act_type from excer_table order by time desc limit (24*60);";
        	long now = Calendar.getInstance().getTimeInMillis();
        	long before = now - (long)(30*24*60*60*1000);
        	long distance = days*24*60*60*1000;
        	
        	String query = "DELETE FROM excer_table where time < " + before + ";";
        	this.hDB.rawQuery(query);	// 이전 기록 삭제
        	before = now - distance;
        	query = "select act_type from excer_table where time <= " + now + " and time >= " + before + ";";
        	Cursor act = this.hDB.rawQuery(query);
        	
        	double retVal = 0;
        	act.moveToFirst();
        	for(int i = 0; i < act.getCount(); i++){
        		switch(act.getInt(0)){
        			case ActionService.ACTION_RUN:
        				retVal += 6;
        				break;
        			case ActionService.ACTION_WALK:
        				retVal += 1.75;
        				break;
        			case ActionService.ACTION_STAY:
        				retVal += 0.3;
        				break;
        			default:
        				break;
        		}
        	}
        	retVal += (days*1440 - act.getCount())*0.15;
        	act.close();
//        	long now = new java.util.Date().getTime();
//        	String query = "select menu from menu_log where time <= " + now + " and time >= " + before + ";";
        	
        	return this.일일신진대사량*days+retVal;
        }
        
        public double estimateWeight(int days){        	
        	return this.weight + ( ( (this.calculateIntakeCalories(days) - this.burnedUpCalories(days)) / WeightEstimator.caloriesForLose1Kg ) );        	
        }
        
}